package stl

import (
	"path/filepath"
	"regexp"

	msmath "gitee.com/yrwy/msgo/pkg/math"
)

func MergeMap[T comparable, V any](l map[T]V, r map[T]V, update bool) map[T]V {
	if l == nil {
		return r
	}
	for k, v := range r {
		if _, ok := l[k]; ok {
			if update {
				l[k] = v
			}
		} else {
			l[k] = v
		}
	}
	return l
}

func BestMatchMap[K comparable, V any](m map[K]V, pattern K, threshold float32, f func(K, K) float32) (V, bool) {
	if v, ok := m[pattern]; ok {
		return v, true
	}
	max_match := float32(0)
	var ret_value V
	for k, v := range m {
		r := f(k, pattern)
		if r >= threshold && r > max_match {
			max_match = r
			ret_value = v
		}
	}
	return ret_value, max_match > 0
}

func MatchMapWith[T comparable, V any](m map[T]V, match func(T) bool, f func(T, V) error) error {
	for k, v := range m {
		if match(k) {
			err := f(k, v)
			if err != nil {
				return err
			}
		}
	}
	return nil
}

// 通配符匹配map
func MatchMap[V any](m map[string]V, pattern string, f func(string, V) error) error {
	if v, ok := m[pattern]; ok {
		return f(pattern, v)
	}
	for k, v := range m {
		if ok, _ := filepath.Match(pattern, k); ok {
			err := f(k, v)
			if err != nil {
				return err
			}
		}
	}
	return MatchMapWith(m, func(k string) bool {
		ok, _ := filepath.Match(pattern, k)
		return ok
	}, f)
}

// '*' - matches zero or more characters
// '?' - matches one character
func MatchMapWildcard[V any](m map[string]V, pattern string, f func(string, V) error) error {
	if v, ok := m[pattern]; ok {
		return f(pattern, v)
	}
	return MatchMapWith(m, func(k string) bool {
		return msmath.MatchWildcard(pattern, k)
	}, f)
}

func MatchMapReg[V any](m map[string]V, reg *regexp.Regexp, f func(string, V) error) error {
	if v, ok := m[reg.String()]; ok {
		return f(reg.String(), v)
	}
	return MatchMapWith(m, func(k string) bool {
		return reg.MatchString(k)
	}, f)
}
